using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml;
using System.Xml.Linq;

namespace N3P.WCF.Proxyless.FullDuplex.Silverlight
{
    internal class CustomBodyWriter : BodyWriter
    {
        private readonly MethodInfo _method;
        private readonly IList<XElement> _elements;
        private readonly string _ns;
        private static readonly Dictionary<Type, string> Namespaces = new Dictionary<Type, string>();
        

        public CustomBodyWriter(Type contractType, MethodInfo method, IList<XElement> elements) : base(true)
        {
            if (!Namespaces.ContainsKey(contractType))
            {
                var sc = (ServiceContractAttribute)contractType.GetCustomAttributes(typeof (ServiceContractAttribute), false).First();
                _ns = Namespaces[contractType] = (sc.Namespace ?? "http://tempuri.org").TrimEnd('/') + "/";
            }
            else
            {
                _ns = Namespaces[contractType];
            }

            _method = method;
            _elements = elements;
        }

        /// <summary>
        /// When implemented, provides an extensibility point when the body contents are written.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Xml.XmlDictionaryWriter"/> used to write out the message body.</param>
        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement(_method.Name, _ns);
            var @params = _method.GetParameters();

            for (var i = 0; i < @params.Length; i++)
            {
                writer.WriteNode(_elements[i].CreateReader(ReaderOptions.OmitDuplicateNamespaces), false);
            }

            writer.WriteEndElement();
            writer.Flush();
        }
    }
}